#include "fourier.h"
#include <muParser.h>
#include "math.h"
#include "complex.h"
#include "qlist.h"
#include<QTime>

Fourier::Fourier(mu::Parser p, QString var, int m)
{
    this->parser = p;
    this->m=m;
    QTime t;
    t.start();
    obtenerPolinomio(var);
    this->tiempoEjecucion = t.elapsed();
}
void Fourier::obtenerPolinomio(QString var)
{
    int N = pow(2,this->m);
    QList<Complex> Z;
    QList<Complex> C;
    QList<Complex> D;
    for(int i=0;i<=N;i++)
    {
        Z<<Complex(0,0);
        C<<Complex(0,0);
        D<<Complex(0,0);
    }
    for(int k=0; k<=N-1; k++)
    {
        Z[k]= Complex::expo((((-2)*M_PI*k)/N));
        double varN=((2*M_PI*k)/N);
        parser.DefineVar(var.toStdString(), &varN);
        C[k]= Complex(this->parser.Eval(),0);
        qDebug("Real: %f. Imaginario: %f",C[k].real, C[k].imaginario);
    }
    for(int n=0; n<=this->m-1;n++){
        for(int k=0; k<=pow(2,m-n-1)-1;k++){
            for(int j=0; j<=pow(2,n)-1;j++){
                Complex u = C[pow(2,n)*k+j];
                Complex v = Z[j*pow(2, m-n-1)] * C[pow(2,n)*k+pow(2,m-1)+j];
                D[pow(2,n+1)*k+j] =(u+v)/2;
                D[pow(2,n+1)*k+j+pow(2,n)] = (u-v)/2;
            }
        }
        for(int j=0;j<N; j++){
            C[j] = D[j];
        }
    }
    /*for(int i=0;i<N;i++)
    {
        qDebug("(a,b): (%f,%f)",C[i].real,C[i].imaginario);
    }*/
    for(int i=0;i<N/2;i++)
    {
        this->a<<0;
        this->b<<0;
    }
    this->a[0]=C[0].real;
    this->b[0]=C[0].imaginario;
    for(int i=1; i<N/2;i++){
        this->a[i]=C[i].real+C[N-i].real;
        this->b[i]=C[i].imaginario-C[N-i].imaginario;
    }

}
double Fourier::evaluar(double x)
{
    double resultado=this->a[0]/2;
    for(int n=1;n<pow(2,this->m)/2;n++)
    {
        resultado+=this->a[n]*cos(n*x)+this->b[n]*sin(n*x);
    }
    return resultado;
}
double Fourier::evaluar_maquina(double x)
{
    parser.DefineVar("x", &x);
    return this->parser.Eval();
}
